package com.zenithmind.coding.config.security;

import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 安全端点注册表 - 遵循开闭原则，支持动态添加端点配置
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Component
public class SecurityEndpointRegistry {

    private final Map<EndpointType, Set<String>> endpointMap = new EnumMap<>(EndpointType.class);

    public SecurityEndpointRegistry() {
        initializeDefaultEndpoints();
    }

    /**
     * 初始化默认端点配置
     */
    private void initializeDefaultEndpoints() {
        // OpenAPI端点
        addEndpoints(EndpointType.AUTH_WHITELIST,
            "/v3/api-docs/**",
            "/swagger-ui/**",
            "/swagger-ui.html",
            "/doc.html",
            "/webjars/**",
            "/favicon.ico",
            "/knife4j/**",
            "/knife4j-ui/**",
            "/knife4j.html"
        );

        // 公开端点
        addEndpoints(EndpointType.PUBLIC,
            "/api/zenithMind/v1/problems/public/**",
            "/api/zenithMind/v1/problems/search",
            "/api/zenithMind/v1/problems/categories",
            "/api/zenithMind/v1/problems/difficulty/**",
            "/api/zenithMind/v1/problems/popular",
            "/api/zenithMind/v1/problems/latest",
            "/api/zenithMind/v1/problems/*/preview",
            "/api/zenithMind/v1/code/execution/demo",
            "/api/zenithMind/v1/languages",
            "/api/zenithMind/v1/code/formatter/templates",
            "/api/zenithMind/v1/submissions/statistics/public",
            "/api/zenithMind/v1/submissions/leaderboard",
            "/actuator/**",
            "/health",
            "/info"
        );

        // 用户端点
        addEndpoints(EndpointType.USER,
            "/api/zenithMind/v1/problems/**",
            "/api/zenithMind/v1/code/**",
            "/api/zenithMind/v1/submissions/**"
        );

        // 出题者端点
        addEndpoints(EndpointType.AUTHOR,
            "/api/zenithMind/v1/problems/create",
            "/api/zenithMind/v1/problems/*/edit",
            "/api/zenithMind/v1/problems/*/delete",
            "/api/zenithMind/v1/problems/*/test-cases",
            "/api/zenithMind/v1/problems/*/solutions"
        );

        // 管理员端点
        addEndpoints(EndpointType.ADMIN,
            "/api/zenithMind/v1/problems/admin/**",
            "/api/zenithMind/v1/code/admin/**",
            "/api/zenithMind/v1/submissions/admin/**",
            "/api/zenithMind/v1/manage/**"
        );
    }

    /**
     * 添加端点
     * 
     * @param type 端点类型
     * @param endpoints 端点列表
     */
    public void addEndpoints(EndpointType type, String... endpoints) {
        endpointMap.computeIfAbsent(type, k -> new HashSet<>())
                  .addAll(Arrays.asList(endpoints));
    }

    /**
     * 移除端点
     * 
     * @param type 端点类型
     * @param endpoints 端点列表
     */
    public void removeEndpoints(EndpointType type, String... endpoints) {
        Set<String> endpointSet = endpointMap.get(type);
        if (endpointSet != null) {
            Arrays.asList(endpoints).forEach(endpointSet::remove);
        }
    }

    /**
     * 获取指定类型的端点数组
     * 
     * @param type 端点类型
     * @return 端点数组
     */
    public String[] getEndpoints(EndpointType type) {
        Set<String> endpoints = endpointMap.get(type);
        return endpoints != null ? endpoints.toArray(new String[0]) : new String[0];
    }

    /**
     * 获取所有公开端点（包括白名单和公开端点）
     * 
     * @return 公开端点数组
     */
    public String[] getAllPublicEndpoints() {
        Set<String> allPublic = new HashSet<>();
        allPublic.addAll(endpointMap.getOrDefault(EndpointType.AUTH_WHITELIST, Collections.emptySet()));
        allPublic.addAll(endpointMap.getOrDefault(EndpointType.PUBLIC, Collections.emptySet()));
        return allPublic.toArray(new String[0]);
    }

    /**
     * 检查端点是否存在
     * 
     * @param type 端点类型
     * @param endpoint 端点
     * @return 是否存在
     */
    public boolean containsEndpoint(EndpointType type, String endpoint) {
        Set<String> endpoints = endpointMap.get(type);
        return endpoints != null && endpoints.contains(endpoint);
    }

    /**
     * 获取端点数量
     * 
     * @param type 端点类型
     * @return 端点数量
     */
    public int getEndpointCount(EndpointType type) {
        Set<String> endpoints = endpointMap.get(type);
        return endpoints != null ? endpoints.size() : 0;
    }

    /**
     * 清空指定类型的端点
     * 
     * @param type 端点类型
     */
    public void clearEndpoints(EndpointType type) {
        endpointMap.remove(type);
    }

    /**
     * 获取所有端点类型
     * 
     * @return 端点类型集合
     */
    public Set<EndpointType> getAllEndpointTypes() {
        return endpointMap.keySet();
    }

    /**
     * 端点类型枚举
     */
    public enum EndpointType {
        /**
         * 认证白名单端点（完全跳过认证）
         */
        AUTH_WHITELIST,
        
        /**
         * 公开端点（允许匿名访问）
         */
        PUBLIC,
        
        /**
         * 用户端点（需要用户认证）
         */
        USER,
        
        /**
         * 出题者端点（需要出题者角色）
         */
        AUTHOR,
        
        /**
         * 管理员端点（需要管理员角色）
         */
        ADMIN
    }
}
